/* 
 * File:   toroidalArrayImpl.c
 * Author: Nikolas Wolfe
 */

/* =============================================================================
 * Defines the implementation of a toroidal array
 */

#include <stdlib.h>
#include <stdio.h>
#include "toroidalArray.h"

/* =============================================================================
 * create a new toroidal array
 */
struct array* createToroidalArray( int WIDTH, int HEIGHT )
{
    struct array * retArr = malloc((WIDTH*HEIGHT+3) * sizeof (int));
    retArr->arr[ WIDTH * HEIGHT ];
    retArr->length = WIDTH * HEIGHT;
    retArr->xMax = WIDTH;
    retArr->yMax = HEIGHT;
    return retArr;
}

/* =============================================================================
 * set a value in the toroidal array
 */
void set( struct array* arr, int x, int y, int val )
{
    int index; 
    index = calculateIndex( arr, x, y );
    arr->arr[ index ] = val;
}
 
/* =============================================================================
 * get a value from the array 
 */
int get( struct array* arr, int x, int y )
{
    int index, retVal;
    index = calculateIndex( arr, x, y );
    retVal = arr->arr[index];
    return retVal;
}

/* =============================================================================
 * index calculation for toroidal arrays, offsets and boundary conditions
 */
int calculateIndex( struct array* arr, int x, int y )
{
    int index;
    int max = getYMax( arr );
    int newX = correctXForToroidalProperty( arr, x );
    int newY = correctYForToroidalProperty( arr, y );
    index = (( newX * max ) + newY );
    return index;
}

int correctXForToroidalProperty( struct array* arr, int x )
{
    int xMax = getXMax( arr );
    if( x < 0 || x >= xMax)
    {
        x = abs((xMax - abs( x ))) % xMax; 
        return x;
    }
    else {
        return x;
    }
}

int correctYForToroidalProperty( struct array* arr, int y )
{
    int yMax = getYMax( arr );
    if( y < 0 || y >= yMax)
    {
        y = abs((yMax - abs( y ))) % yMax; 
        return y;
    }
    else {
        return y;
    }
}

/* =============================================================================
 * get the max X value
 */
int getXMax( struct array* arr )
{
    return arr->xMax;
}

/* =============================================================================
 * get the max Y value
 */
int getYMax( struct array* arr )
{
    return arr->yMax;
}

/* =============================================================================
 * get the size of the array
 */
int getSize( struct array* arr )
{
    return arr->length;
}

